﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace LumenLiquid.InGame.world
{
    class Terrain
    {
        private struct VertexPosition
        {
            public Vector2 Position { get; set; }

            public static readonly VertexDeclaration VertexDeclaration =
                new VertexDeclaration(new VertexElement(0, VertexElementFormat.Vector2, VertexElementUsage.Position, 0));
        }


        private Effect _terrain;
        private Texture2D _heightmap;
        private VertexPosition[] _vertices;
        private int[] _indices;
        private const int LOD = 3;

        private readonly Vector2[] _positionIndex = new Vector2[]
            {
                new Vector2(1, -1), new Vector2(0.5f, -1), new Vector2(0, -1), new Vector2(-0.5f, -1),              // X X X X
                new Vector2(1, -0.5f), new Vector2(-0.5f, -0.5f),                                                   // X - - X
                new Vector2(1, 0), new Vector2(-0.5f, 0),                                                           // X - - X
                new Vector2(1, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0, 0.5f), new Vector2(-0.5f, 0.5f),      // X X X X
                                                                                                                    // - - - -
                new Vector2(0.5f, -0.5f), new Vector2(0, -0.5f),                                                    // - X X -
                new Vector2(0.5f, 0), new Vector2(0, 0)                                                             // - X X -
            };                                                                                                      // - - - -

        private void InitializeVertices()
        {
            //Initialize for 16x16. Using 17x17 to remove gaps

            _vertices = new VertexPosition[33 * 33];

            for (int x = 0; x <= 32; x++)
            {
                for (int y = 0; y <= 32; y++)
                {
                    _vertices[x + y * 33] = new VertexPosition { Position = new Vector2(x, y) };//LOD = 1
                }
            }

            _indices = new int[32 * 32 * 6];
            int counter = 0;

            for (int y = 0; y < 32; y++)
            {
                for (int x = 0; x < 32; x++)
                {
                    int topLeft = x + y * 33;
                    int topRight = (x + 1) + y * 33;
                    int lowerLeft = x + (y + 1) * 33;
                    int lowerRight = (x + 1) + (y + 1) * 33;

                    _indices[counter++] = lowerLeft;
                    _indices[counter++] = topRight;
                    _indices[counter++] = topLeft;

                    _indices[counter++] = lowerLeft;
                    _indices[counter++] = lowerRight;
                    _indices[counter++] = topRight;
                }
            }
        }

        public void Init()
        {
            InitializeVertices();

            _terrain = Main.Instance.Effectmanager.GetGroupEffect(Path.Ressources.ClipMapEffect,
                                                                  Path.Ressources.InGameGroup);
            _heightmap = Main.Instance.Texturemanager.GetGlobalTexture2D(Path.Content.Textures + "height1");
        }

        #region XNA Functions
        public void Update(GameTime gameTime)
        {

        }

        public void Draw(GameTime gameTime)
        {
            _terrain.CurrentTechnique = _terrain.Techniques["WireframeWhite"];
            _terrain.Parameters["View"].SetValue(MainGame.Instance.Camera);
            _terrain.Parameters["Projection"].SetValue(MainGame.Instance.Projection);
            _terrain.Parameters["CameraPos"].SetValue(MainGame.Instance.CameraPosition);
            _terrain.Parameters["Heightmap"].SetValue(_heightmap);

            int sectors = 16;
            foreach (EffectPass pass in _terrain.CurrentTechnique.Passes)
            {


                for (int l = 0; l < LOD; l++)
                {
                    _terrain.Parameters["LODscale"].SetValue(1 << l);

                    for (int i = 0; i < sectors; i++)
                    {
                        _terrain.Parameters["Position"].SetValue(_positionIndex[i]);
                        pass.Apply();

                        Main.Instance.Device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, _vertices, 0,
                                                                                               _vertices.Length, _indices, 0, _indices.Length / 3,
                                                                                               VertexPosition.VertexDeclaration);
                    }
                    sectors = 12;
                }
            }
        }
        #endregion
    }
}
